package ace.tool.generate.code.impl.manager.ui;

import ace.tool.generate.code.impl.generator.DefaultGenerator;
import ace.tool.generate.code.impl.manager.common.EntityModelManager;
import ace.tool.generate.code.impl.resolver.ui.model.bo.*;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import org.apache.commons.io.FileUtils;

/**
 * @author caspar
 * @date 2024/1/11 10:12 core project manager generator
 */
@RequiredArgsConstructor
public class UiManager {
  private final UiProjectContext context;
  private final EntityModelManager entityModelManager = new EntityModelManager();

  @SneakyThrows
  public void generate() {

    this.generateFrameworkDirs();

    this.generateMockServerApis();

    this.generateMockServerApiIndex();

    this.generateApiConfig();

    this.generateTypesDirResponses();

    this.generateServerApis();

    this.generateServices();

    this.generateEnums();

    this.generateViewLists();
  }

  private void generateMockServerApiIndex() {
    UiMockServerApiIndexClassInfo uiMockServerApiIndexClassInfo =
        this.context.getUiProjectInfo().getUiMockServerApiIndexClassInfo();
    String templateFile = "/schema/ui-project/UiProjectMockServerApiIndex.ftl";
    String outputFileFullName =
        uiMockServerApiIndexClassInfo.getInfo().getUncapitalizeClassFileFullName();
    new DefaultGenerator(templateFile, outputFileFullName)
        .generate(uiMockServerApiIndexClassInfo, true);
  }

  @SneakyThrows
  private void generateFrameworkDirs() {
    for (String dir : this.context.getUiProjectInfo().getFrameworkDirs()) {
      FileUtils.forceMkdir(new File(dir));
    }
  }

  private void generateServices() {
    this.context.getUiProjectInfo().getUiServiceClassInfos().forEach(this::generateService);
  }

  private void generateService(UiServiceClassInfo uiServiceClassInfo) {
    String templateFile = "/schema/ui-project/UiProjectService.ftl";
    String outputFileFullName = uiServiceClassInfo.getInfo().getUncapitalizeClassFileFullName();
    new DefaultGenerator(templateFile, outputFileFullName).generate(uiServiceClassInfo);
  }

  private void generateServerApis() {
    this.context.getUiProjectInfo().getUiServerApiClassInfos().forEach(this::generateServerApi);
  }

  private void generateServerApi(UiServerApiClassInfo uiServerApiClassInfo) {
    String templateFile = "/schema/ui-project/UiProjectServerApi.ftl";
    String outputFileFullName = uiServerApiClassInfo.getInfo().getUncapitalizeClassFileFullName();
    new DefaultGenerator(templateFile, outputFileFullName).generate(uiServerApiClassInfo);
  }

  private void generateApiConfig() {
    this.generateApiConfig(this.context.getUiProjectInfo().getApiConfigClassInfo());
  }

  private void generateApiConfig(UiApiConfigClassInfo uiApiConfigClassInfo) {
    Map<String, Object> model = new HashMap<>();
    model.put("className", uiApiConfigClassInfo.getInfo().getClassName());
    model.put("uncapitalizeClassName", uiApiConfigClassInfo.getInfo().getUncapitalizeClassName());
    model.put("projectName", uiApiConfigClassInfo.getProjectModuleName());
    model.put("fields", uiApiConfigClassInfo.getFields());

    String templateFile = "/schema/ui-project/UiProjectModuleApiConfig.ftl";
    String outputFileFullName = uiApiConfigClassInfo.getInfo().getUncapitalizeClassFileFullName();
    new DefaultGenerator(templateFile, outputFileFullName).generate(model);
  }

  private void generateViewLists() {
    this.context.getUiProjectInfo().getUiViewListClassInfos().forEach(this::generateViewList);
  }

  private void generateViewList(UiViewListClassInfo uiViewListClassInfo) {
    Map<String, Object> model = new HashMap<>();
    model.put("className", uiViewListClassInfo.getInfo().getClassName());
    model.put("remark", uiViewListClassInfo.getModel().getRemark());
    model.put("fields", uiViewListClassInfo.getModel().getFields());
    model.put("idField", uiViewListClassInfo.getModel().getIdField());
    model.put("apiConfigPrefix", uiViewListClassInfo.getApiConfigPrefix());

    String templateFile = "/schema/ui-project/UiProjectViewList.ftl";
    String outputFileFullName = uiViewListClassInfo.getInfo().getClassFileFullName();
    new DefaultGenerator(templateFile, outputFileFullName).generate(model);
  }

  private void generateMockServerApis() {
    this.context
        .getUiProjectInfo()
        .getMockServerApiClassInfos()
        .forEach(this::generateMockServerApis);
  }

  private void generateMockServerApis(UiMockServerApiClassInfo mockServerApiClassInfo) {

    String templateFile = "/schema/ui-project/UiProjectMockServerApi.ftl";
    String outputFileFullName = mockServerApiClassInfo.getInfo().getUncapitalizeClassFileFullName();
    new DefaultGenerator(templateFile, outputFileFullName).generate(mockServerApiClassInfo);
  }

  private void generateTypesDirResponses() {
    this.context.getUiProjectInfo().getResponses().forEach(this::generateTypesDirResponse);
  }

  private void generateTypesDirResponse(ResponseClassInfo response) {

    Map<String, Object> model = new HashMap<>();
    model.put("remark", response.getModel().getRemark());
    model.put("className", response.getInfo().getClassName());
    model.put("fields", response.getModel().getFields());

    String templateFile = "/schema/ui-project/UiProjectTypesResponse.ftl";
    String outputFileFullName = response.getInfo().getClassFileFullName();
    new DefaultGenerator(templateFile, outputFileFullName).generate(model);
  }

  private void generateEnums() {
    context.getUiProjectInfo().getEnumClassInfos().forEach(this::generateEnum);
  }

  private void generateEnum(UiEnumClassInfo enumClassInfo) {
    String templateFile = "/schema/ui-project/UiProjectEnumClass.ftl";
    String outputFileFullName = enumClassInfo.getInfo().getClassFileFullName();
    Map<String, Object> model = new HashMap<>();
    model.put("remark", enumClassInfo.getRemark());
    model.put("className", enumClassInfo.getInfo().getClassName());
    model.put("codeClass", enumClassInfo.getCodeClass());
    model.put("fields", enumClassInfo.getFields());

    new DefaultGenerator(templateFile, outputFileFullName).generate(model);
  }
}
